/*************************************************************************
	> File Name: protocolhandler.cpp
	> Author: xuwenlong
	> Mail: myxuan475@126.com 
	> Created Time: 2018年01月24日 星期三 17时08分04秒
 ************************************************************************/

#include<stdio.h>
#include "protocolhandler.h"
#include "../../globalmsg.h"
#include <utils/socket_request.h>
#include <devices/devices.h>
#include <sys/stat.h>

ProtocolHandler::ProtocolHandler(
        U16 uflag,
        TransportInterface *interface):
    RPCProtocol(interface,uflag&DO_ENCRYPT),
    m_iMaxId(0),
    m_state_lock(TRUE),
    m_wait_lock(TRUE),
    m_pTimer(NULL),
    m_uFlag(uflag) {

//    if (m_bToken)
//        SetMsgStatus(DAS_REGISTERACQUISITOR,TRUE);
//    if (m_uFlag&HAS_TIMER) {
        m_pTimer = new Timer("protocolhandler",this);
        m_pTimer->Start(300,kPeriodic);
        //    }
}

ProtocolHandler::~ProtocolHandler()
{
    if (m_pTimer) {
        m_pTimer->Stop();
        delete m_pTimer;
    }
}

void ProtocolHandler::OnResult(int msgId, Json::Value &result)
{
    LOG_TRACE();

    AutoLock auto_lock(m_state_lock);
    if (m_pRequestJson.find(msgId-1000) == m_pRequestJson.end()){
        LOG_ERR("msgId %d not found",msgId);
        return;
    }

    RequestJson *request = m_pRequestJson[msgId-1000];
    if (request) {
        if (!request->handleJsonRpc(DAS_SUCCESS,result)) {
//            LOG_ERR("msgId = %d:instance has been deleted",msgId);
            return;
        }
        delete request;
        m_pRequestJson.erase(msgId-1000);
    }
    else{
        LOG_WARN("%d has been time out",msgId);
    }
}

void ProtocolHandler::OnRequest(int msgId, Json::Value &request)
{
    LOG_TRACE();

    Json::Value result;
    Json::Value params;
    DAS_RESULT ret = DAS_INVALID;

    std::string method;

    if (request.isMember("method"))
        method = request["method"].asString();

    if (!GetMsgStatus(DAS_REGISTERACQUISITOR,GetIndex()) &&
            !(m_uFlag&HAS_TOKEN)) {
        SendError(msgId,method,false,GetError(DAS_INVALID));
        return;
    }

    if (request.isMember("params"))
        params = request["params"];

    ret = OnRequest(msgId,method,params,result);

    if (ret == DAS_RESULT_MAX) {
        m_wait_lock.Acquire();
        WaitJson wJson(msgId,method);
        m_vectorWaitJson.push_back(wJson);
        m_wait_lock.Release();
        return;
    }
    else if (ret == DAS_DONOTHING)
        return;

//    if (m_uFlag & SYNC_SEND) {
//        m_pAckJson->push_back(msgId,method,result,ret);
//    }
//    else {
        if (ret == DAS_SUCCESS) {
           SendResult(msgId,method,result);
        }
        else if(ret == DAS_NOTPASS) {
           SendResult(msgId,method,false);
        }
        else
           SendResult(msgId,method,result/*,GetError(ret)*/);
//    }
}

DAS_RESULT ProtocolHandler::OnRequest(int msgId,const std::string &method, const Json::Value &params, Json::Value &result)
{
#define JSON_METHOD_EQUAL(name) (method==name)
#if defined(DAS_ACQUIRE) || defined(DAS_CLIENT)
    DAS_RESULT ret = DAS_INVALID;
    if (JSON_METHOD_EQUAL("checkHeartbeat")) {
        result = GetMsgStatus(DAS_REGISTERACQUISITOR,GetIndex()) && GetMsgStatus(DAS_MSG_STATUS,GetIndex());
        ret = DAS_SUCCESS;
    }
    else if (JSON_METHOD_EQUAL("heartBeat")) {
        result = true;
        ret = DAS_SUCCESS;
    }
    else if (JSON_METHOD_EQUAL("loginUser")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
        if (!module)
            return DAS_NOTPASS;
        ret = module->loginUser(params);
        result = (ret == DAS_SUCCESS);
    }
    else if(JSON_METHOD_EQUAL("updateDeviceList")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            return ret;
        }
        ret = module->updateDeviceList(params,result);
    }
    else if(JSON_METHOD_EQUAL("updateTemplate")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            return ret;
        }
        ret = module->updateTemplate(params,result);
        if (ret == DAS_SUCCESS)
            result = true;
    }
    else if(JSON_METHOD_EQUAL("updateCommunication")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            return ret;
        }
        ret = module->updateCommunication(params,result);
        if (ret == DAS_SUCCESS)
            result = true;
    }
    else if(JSON_METHOD_EQUAL("updateDevices")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            return ret;
        }
        ret = module->updateDevices(params,result);
        if (ret == DAS_SUCCESS)
            result = true;
    }
    else if(JSON_METHOD_EQUAL("getTMCStatus")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = SocketRequest(ACQ_PORT).sendRequest(method,params);
            return DAS_SUCCESS;
        }
        ret = module->getTMCStatus(params,result);
    }
    else if(JSON_METHOD_EQUAL("setTMCTimer")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = false;
            return DAS_SUCCESS;
        }
        ret = module->setTMCTimer(params);
        result = (ret == DAS_SUCCESS);
    }
    else if(JSON_METHOD_EQUAL("setTMCSwitch")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = false;
            return DAS_SUCCESS;
        }
        ret = module->setTMCSwitch(params);
        result = (ret == DAS_SUCCESS);
    }
    //setTMCTiming
    else if(JSON_METHOD_EQUAL("setTMCTiming")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = false;
            return DAS_SUCCESS;
        }
        ret = module->setTMCTiming(params);
        result = (ret == DAS_SUCCESS);
    }
    else if(JSON_METHOD_EQUAL("setTMCGearPos")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = false;
            return DAS_SUCCESS;
        }
        ret = module->setTMCGearPos(params);
        result = (ret == DAS_SUCCESS);
    }
    //设置档位

    //设置工作模式
    else if(JSON_METHOD_EQUAL("setTMCMode")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = false;
            return DAS_SUCCESS;
        }
        ret = module->setTMCMode(params);
        result = (ret == DAS_SUCCESS);
    }
    else if(JSON_METHOD_EQUAL("setTMCLock")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = false;
            return DAS_SUCCESS;
        }
        ret = module->setTMCLock(params);
        result = (ret == DAS_SUCCESS);
    }
    else if(JSON_METHOD_EQUAL("getIOStatus")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = false;
            return DAS_SUCCESS;
        }
        ret = module->getIOStatus(params,result);
//        result = (ret == DAS_SUCCESS);
    }
    else if(JSON_METHOD_EQUAL("setIOStatus")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
        if (!module) {
            result = false;
            return DAS_SUCCESS;
        }
        ret = module->setIOStatus(params);
        result = (ret == DAS_SUCCESS);
    }
    else if(JSON_METHOD_EQUAL("updatePackets")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_REMOTESERVICE));
        if (!module) {
            return ret;
        }
        ret = module->updatePackets(msgId,params,result);
    }
    else if (JSON_METHOD_EQUAL("executeScript")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
        if (!module) {
            return ret;
        }
        ret = module->executeScript(params,result);
    }
    else if (JSON_METHOD_EQUAL("getAcquisitorStatus")) {
        ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
        if (!module) {
            return ret;
        }
        ret = module->getAcquisitorStatus(result);
    }
    else if (JSON_METHOD_EQUAL("uploadFile")) {
        string file = params["name"].asString();
        int seek = params["seek"].asUInt64();
        int uplen = 0;
        FILE *fd = fopen(file.c_str(),"r");
        if (!fd) {
            return DAS_FILE_OPENFAILD;
        }
        fseek(fd, 0, SEEK_END);
        long filelen = ftell(fd);
        long length = filelen - seek;

        if (length <= 0) {
            LOG_ERR("seek is error!");
            return DAS_FILE_OPENFAILD;
        }

        if (length >= MAX_FILE_SIZE) {
            uplen = MAX_FILE_SIZE;
        }
        else
            uplen = length;

        char *src = (char*)malloc(uplen+1);

        fseek(fd,seek,SEEK_SET);
        fread(src,uplen,1,fd);
        src[uplen] = 0;
        fclose(fd);

        Json::Value params;
        params["name"] = file;
        params["content"] = src;
        params["seek"] = seek;
        return DAS_SUCCESS;
    }
    else if (JSON_METHOD_EQUAL("downloadFile")) {
        const string &name = params["name"].asString();
        const string &content = params["content"].asString();
        int seek = params["seek"].asUInt64();

        mkdir(name.c_str(),0777);

        FILE *fp;
        if (access(name.c_str(), R_OK) != 0) {//not exists
          fp = fopen(name.c_str(), "w+");
        } else  {
          fp = fopen(name.c_str(), "r+");
        }

        if (!fp) {
            return DAS_FILE_OPENFAILD;
        }

        //
        fseek(fp,seek,SEEK_SET);
        int wlen = fwrite(content.c_str(),1,content.length(),fp);

        fseek(fp,0,SEEK_END);
        long int filelen = ftell(fp);
        if (seek+wlen >= filelen)
            result = wlen;
        else
            result = (int)(filelen-seek);
        return DAS_SUCCESS;
    }
    else if (JSON_METHOD_EQUAL("registerAgain")) {
        SetMsgStatus(DAS_REGISTERACQUISITOR,FALSE,GetIndex());
        result = true;
        ret = DAS_SUCCESS;
    }
    else if (!strncmp(method.c_str(),"get",3) || !strncmp(method.c_str(),"debug",5)) {
        if (JSON_METHOD_EQUAL("getDeviceStatus")) {
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (module) {
                ret = module->getDeviceStatus(params,result);
            }
            else {
                Devices dev;
                ret = dev.getDeviceStatus(params,result);
            }
        }
        else if (JSON_METHOD_EQUAL("getAcquireValues")) {
            Devices dev;
            ret = dev.getAcquireValues(params,result);
        }
        else if (JSON_METHOD_EQUAL("getDataCenter")) {
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
            if (!module) {
                return ret;
            }
            ret = module->getDataCenter(result);
        }
        else if (JSON_METHOD_EQUAL("getAcquisitorInfo")){
            ModuleInterface *module;
            module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
            ret = module->getAcquisitorInfo(
                        result);
        }
        else if (JSON_METHOD_EQUAL("getGateway")) {
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
            if (!module) {
                return ret;
            }
            ret = module->getGateway(result);
        }
        else if (JSON_METHOD_EQUAL("getChnList")) {
            Devices dev;
            ret = dev.getChnList(result);
        }
        else if (JSON_METHOD_EQUAL("getTempList")) {
            Devices dev;
            ret = dev.getTempList(result);
        }
        else if (JSON_METHOD_EQUAL("getDeviceList")){
            Devices dev;
            ret = dev.getDeviceList(params,result);
        }
        else if (JSON_METHOD_EQUAL("getDeviceInfo")){
            Devices dev;
            ret = dev.getDeviceInfo(params,result);
        }
        else if (JSON_METHOD_EQUAL("debugDevice")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (!module) {
                result = SocketRequest(ACQ_PORT).sendRequest(method,params);
                return DAS_SUCCESS;
            }
            ret = module->debugDevice(
                        params,result);
        }
        //getAcquireData
        else if (JSON_METHOD_EQUAL("getAcquireData")){
            Devices dev;
            ret = dev.getAcquireData(params,result);
        }
    }
    else {

        if (JSON_METHOD_EQUAL("setDataCenter")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
            if (!module)
                return ret;
            ret = module->setDataCenter(
                        params);
            if (ret == DAS_SUCCESS) {
                ModuleInterface *mdacq = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
                if (mdacq) {
                    ret = mdacq->connectServer();
                    result = true;
                }
                else {
                    result = SocketRequest(ACQ_PORT).sendRequest("connectServer",params);
                    if (result.isBool() && result.asBool() == true)
                        ret = DAS_SUCCESS;
                    else
                        ret = DAS_STOREERROR;
                }
            }

        }
        else if (JSON_METHOD_EQUAL("setAcquisitorInfo")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
            if (!module)
                return ret;
            ret = module->setAcquisitorInfo(
                        params);
            result = (ret == DAS_SUCCESS);
        }
        else if (JSON_METHOD_EQUAL("setGateway")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
            if (!module)
                return ret;
            ret = module->setGateway(
                        params);
            result = (ret == DAS_SUCCESS);
        }
        else if (JSON_METHOD_EQUAL("connectServer")) {
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (!module) {
                return ret;
            }
            result = true;
            ret = module->connectServer();
        }
        else if (JSON_METHOD_EQUAL("clearData")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (!module) {
                return ret;
            }
            ret = module->clearData();
            result = (ret == DAS_SUCCESS);
        }
        else if (JSON_METHOD_EQUAL("startAcquire")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (!module) {
                result = SocketRequest(ACQ_PORT).sendRequest(method,params);
                return DAS_SUCCESS;
            }
            ret = module->startAcquire();
            result = (ret == DAS_SUCCESS);
        }
        else if (JSON_METHOD_EQUAL("stopAcquire")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (!module) {
                result = SocketRequest(ACQ_PORT).sendRequest(method,params);
                return DAS_SUCCESS;
            }
            ret = module->stopAcquire();
            result = (ret == DAS_SUCCESS);
        }
        else if (JSON_METHOD_EQUAL("addDevice")){
            Devices dev;
            ret = dev.addDevice(params);
            result = (ret == DAS_SUCCESS);
        }
        else if (JSON_METHOD_EQUAL("deleteDevice")){
            Devices dev;
            ret = dev.deleteDevice(params);
            result = (ret == DAS_SUCCESS);
        }
        else if (JSON_METHOD_EQUAL("modifyDevice")){
            Devices dev;
            ret = dev.modifyDevice(params);
            result = (ret == DAS_SUCCESS);
        }
        else if(JSON_METHOD_EQUAL("indicateDevice")) {
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (!module) {
                result = SocketRequest(ACQ_PORT).sendRequest(
                            method,params);
                return DAS_SUCCESS;
            }
            ret = module->indicateDevice(
                        params,result);
        }
        else if(JSON_METHOD_EQUAL("setDevice")) {
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (!module) {
                result = SocketRequest(ACQ_PORT).sendRequest(
                            method,params);
                return DAS_SUCCESS;
            }
            ret = module->setDevice(
                        params,result);
        }
        else if (JSON_METHOD_EQUAL("dailyMemory")) {
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_ACQUISITOR));
            if (!module) {
                result = SocketRequest(ACQ_PORT).sendRequest(
                            method,params);
                return DAS_SUCCESS;
            }
            ret = module->dailyMemory(result);
        }
        //readIniFile
        else if (JSON_METHOD_EQUAL("readIniFile")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
            if (!module)
                return ret;
            ret = module->readIniFile(
                        params,result);
        }
        else if (JSON_METHOD_EQUAL("writeIniFile")){
            ModuleInterface *module = ((ModuleInterface*)GetTask(DAS_BASE_INFO));
            if (!module)
                return ret;
            ret = module->writeIniFile(
                        params);
            result = ret==DAS_SUCCESS;
        }
    }
    return ret;
#endif
#undef JSON_METHOD_EQUAL
}

void ProtocolHandler::RunTimer()
{
    RpcParse();
    TimeOut();
}

void ProtocolHandler::StopTimer()
{
    if (m_pTimer)
        m_pTimer->Stop();
}

void ProtocolHandler::TimeOut()
{
    AutoLock auto_lock(m_state_lock);

    std::map<S32,RequestJson *>::iterator iter;
    for (iter = m_pRequestJson.begin();
         iter != m_pRequestJson.end();iter++) {
        S32  index = iter->first;
        RequestJson *request = iter->second;
        if (!request) {
            LOG_WARN("%d has been time out",index+1000);

            continue;
        }
        if (request->IsTimeOut()) {
            if (!request->handleJsonRpc(DAS_TIMEOUT,Json::Value())) {
//                LOG_ERR("msgId = %d:instance has been deleted",index+1000);
                return;
            }
            delete request;
            //                m_pRequestJson[index]=NULL;
            m_pRequestJson.erase(iter);
            break;
        }
    }
}

S32 ProtocolHandler::SendJsonRpc(
        tJsonRpcInterface _interface,
        const std::string &method,
        const Json::Value &params,
        int timeout)
{
    if (method == "registerAcquisitor") {
        if (findMethod(method))
            return -2;
    }
//    else if (method == "telnetStart") {
//        deleteMethod(method);
//    }
    else {
        if (!(m_uFlag & HAS_TOKEN) && !GetMsgStatus(DAS_REGISTERACQUISITOR,GetIndex()))
            return -2;
        // 如果还没有注册，先使用注册;如果注册了，使用心跳
        if (method == "heartBeat") {
            if (findMethod(method))
                return -2;
        }
    }

    int id = generateId(_interface,method,timeout);

    if ((id == -1) || (!SendRequest(id,method,params))) {
        deleteId(id);
        return -1;
    }
    return id;
}

bool ProtocolHandler::ReturnJsonRpc(
        S32 msgId,
        const string &method,
        const Json::Value &result)
{
    return SendResult(msgId,method,result);
}

BOOL ProtocolHandler::SendAsyncJson(
        S32 msgId, tJsonRpcInterface _interface,
        const string &method, const Json::Value &params)
{
    RequestJson *request = m_pRequestJson[msgId-1000];
    if (!request)
        return FALSE;
    request->interface = _interface;
    return SendRequest(msgId,method,params);
}

bool ProtocolHandler::ReturnAsyncResult(
        DAS_RESULT status,
        int waitId,
        const Json::Value &result)
{
    AutoLock lock(m_wait_lock);
    std::vector<WaitJson>::iterator iter;
    for (iter = m_vectorWaitJson.begin();
         iter != m_vectorWaitJson.end();
         iter++) {
        WaitJson& wJson = *iter;
        if (wJson.msgId == waitId) {
            bool ret;
            if (status == DAS_SUCCESS ||
                    status == DAS_RESULT_MAX) {
                ret = SendResult(wJson.msgId,wJson.method,result);
            }
            else
                ret = SendError(wJson.msgId,wJson.method,result,GetError(status));
            if (status != DAS_RESULT_MAX)
                m_vectorWaitJson.erase(iter);
            return ret;
        }
    }
    return false;
}

int ProtocolHandler::generateId(
        tJsonRpcInterface _interface,
        const std::string &method,
        int timeout)
{
    AutoLock auto_lock(m_state_lock);

    S32 index = m_iMaxId+1;

    if (index == 0)
        ++index;

    while (m_pRequestJson.find(index)
           != m_pRequestJson.end()) {
        index++;
        if (index == 0)
            ++index;
    }

    m_iMaxId = index;

    m_pRequestJson.insert(
                std::pair<S32,RequestJson*>(
                    index,
                    new RequestJson(
                        GetIndex(),_interface,
                        method,timeout))
                );

    return (index+1000);
}

void ProtocolHandler::deleteId(S32 msgId)
{
    AutoLock auto_lock(m_state_lock);

    int index = msgId -1000;
    if (m_pRequestJson.find(index)
           != m_pRequestJson.end()) {
        RequestJson *pReqJson = m_pRequestJson[index];
        LOG_WARN("handle:%s",pReqJson->method.c_str());
        delete pReqJson;
        m_pRequestJson.erase(index);
    }
}

bool ProtocolHandler::findMethod(const std::string &method)
{
    AutoLock auto_lock(m_state_lock);

    std::map<S32,RequestJson *>::iterator iter;
    for (iter = m_pRequestJson.begin();
         iter != m_pRequestJson.end();iter++) {
        RequestJson *request = iter->second;
        if (!request)
            continue;
        if (method == request->method) {
            return true;
        }
    }
    return false;
}

void ProtocolHandler::deleteMethod(const string &method)
{
    AutoLock auto_lock(m_state_lock);

    std::map<S32,RequestJson *>::iterator iter;
    for (iter = m_pRequestJson.begin();
         iter != m_pRequestJson.end();) {
        RequestJson *request = iter->second;
        if (!request) {
            iter = m_pRequestJson.erase(iter);
            continue;
        }
        if (method == request->method) {
            iter = m_pRequestJson.erase(iter);
        }
        else {
            iter++;
        }
    }
}
